home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 112 / EnigmaAmiga112CD.iso / dalla rivista / giochi in rete / sorgenti_amislate / remote.c < prev    next >
C/C++ Source or Header  |  1995-08-05  |  36KB  |  1,226 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <intuition/intuition.h>
  4. #include <intuition/intuitionbase.h>
  5. #include <exec/types.h>
  6. #include <libraries/dos.h>            /* contains RETURN_OK, RETURN_WARN #def's */
  7. #include <clib/dos_protos.h>
  8. #include <clib/exec_protos.h>
  9. #include <clib/intuition_protos.h>
  10. #include <clib/graphics_protos.h>
  11. #include <string.h>
  12. #include <graphics/gfxbase.h>
  13.  
  14. #include "DrawLang.h"
  15. #include "Tools.h"
  16. #include "AmiSlate.h"
  17. #include "remote.h"
  18. #include "drawrexx.h"
  19. #include "drawrexx_aux.h"
  20. #include "drawtcp.h"
  21. #include "asl.h"
  22. #include "StringRequest.h"
  23. #include "flood.h"
  24. #include "ilbm.h"
  25.  
  26. #define INTUI_V36_NAMES_ONLY
  27.  
  28. #define MAXARGS 15
  29. #define PAD_CHAR '\1'
  30. #define PAD_STRING "\1"
  31. #define MAGIC_BYTE 200        /* ASCII 200, the E variant used to separate substrings */
  32.  
  33. extern int Not[2];             /* a NOT lookup array */
  34. extern struct Library *IntuitionBase;
  35. extern struct GfxBase *GraphicsBase;
  36. extern struct Window *DrawWindow;
  37. extern struct PaintInfo PState;
  38. extern struct Screen *Scr;
  39. extern FILE *fpIn;
  40. extern FILE *fpOut;
  41. extern BOOL BNetConnect;
  42. extern BOOL BPalettesLocked;
  43. extern BOOL BAcceptingTCP;
  44. extern BOOL BIFFLoadPending;
  45. extern BOOL BProtectInter;
  46. extern char targethost[100];
  47. extern char sBuf[140];
  48. extern char szSendString[256];
  49. extern char szReceiveString[256];
  50. extern char szUserString[256];
  51. extern struct RexxHost *rexxHost;
  52. extern char szRexxOutputFile[200];
  53.  
  54. /* Private local variables */
  55. static int XPen = -1, YPen = -1;
  56. static UWORD wArgs[MAXARGS];
  57. static UWORD wCommand = NOTSENDABLE;
  58. static int nSaveState = MODE_INVALID;
  59. static int nNextArg = -1;
  60. static UWORD uwPreviousMode = MODE_INVALID;        /* used by OutputAction */
  61. static BOOL RemotePenMap[MAXCOLORS];
  62.  
  63. /* 
  64.     Explanation of Modes used here  (#defined in DrawLang.h) :
  65.  
  66.         MODE_COMMAND:   Have read the COMMAND keyword, awaiting command type 
  67.         MODE_DOT:       Awaiting dot co-ordinates
  68.         MODE_PEN:       Awaiting pen co-ordinates
  69.         MODE_LINE:      Awaiting line co-ordinates
  70.         MODE_CIRCLE:    Awaiting circle co-ordinates
  71.         MODE_SQUARE:    Awaiting square co-ordinates
  72.         MODE_POLY:      Awaiting poly co-ordinates
  73.         MODE_FLOOD:     Awaiting flood co-ordinates
  74.         MODE_RASTER:    Awaiting raster info
  75.         
  76.         MODE_MODE:      Awaiting new mode choice
  77.          
  78.         MODEC_RGB:       Read COMMAND_RGB keyword, awaiting RGB values
  79.         MODEC_SIZE:      Read COMMAND_SIZE keyword, awaiting sizing values
  80.     MODEC_SYNCH:     Read COMMAND_SYNCH keyword, awaiting all values
  81.     MODEC_SENDSTRING: Read COMMAND_SENDSTRING keyword (+ string), awaiting chars
  82.         
  83. */
  84.  
  85. /* ---------------- Main remote function --------------------------- */
  86. /*                                                                   */
  87. /* Each time this functin is called it will process one word of      */
  88. /* remote input.  It will return FALSE if it encounters a         */
  89. /* NOTSENDABLE or COMMAND_QUIT char, else TRUE                       */
  90. /*                                     */
  91. /* If fpFile == NULL, we will get our input from the TCP link,       */
  92. /* otherwise we'll read it from that file.                           */
  93. BOOL RemoteHandler(FILE *fpFile, BOOL BEchoToRemote)
  94. {
  95.     UWORD uwNext;
  96.     UBYTE ubRed, ubGreen, ubBlue;
  97.     static UBYTE ubStringIndex = 0;
  98.     static UWORD uwStringType  = 0;
  99.     static LONG lStringType;
  100.     const static LONG lType = REXX_REPLY_MESSAGE, lConnectType = REXX_REPLY_CONNECT;
  101.     BOOL BNotBk, BXorFlag, BFilledFlag;
  102.     int i;
  103.     
  104.     if (fpFile == NULL)
  105.         uwNext = Wread(NULL, FROM_PEER);
  106.     else
  107.         uwNext = Wread(fpFile, FROM_FILE);
  108.  
  109.     if (uwNext == SEND_EMPTY) return(TRUE);    /* Nothing to recieve, but no errors! */
  110.     if ((uwNext == NOTSENDABLE)||(uwNext == SEND_ERROR)) return(FALSE); 
  111.     
  112.     /* If we're in string mode, we listen for nothing else until it's done! */
  113.     if (PState.uwRemoteMode == MODEC_SENDSTRING)
  114.     {
  115.         /* If we don't have a string type yet, the first word should
  116.            be it.  Get it. */
  117.         if (uwStringType == 0) 
  118.         {
  119.             uwStringType = uwNext;
  120.             return(TRUE);
  121.         }
  122.         
  123.         /* Check for special end-of-string marker */
  124.         if (uwNext == STOP_STRING) 
  125.         {
  126.             PState.uwRemoteMode = nSaveState;
  127.             szReceiveString[ubStringIndex] = '\0';
  128.             if (szReceiveString[ubStringIndex-1] == PAD_CHAR)
  129.                 szReceiveString[ubStringIndex-1] = '\0';
  130.             
  131.             if (PState.uwRexxWaitMask & REXX_REPLY_MESSAGE)
  132.             {
  133.                 ((struct rxd_waitevent *) *(&RexxState.array))->res.type    = &lType; 
  134.                 ((struct rxd_waitevent *) *(&RexxState.array))->res.code1   = &lStringType;
  135.                 ((struct rxd_waitevent *) *(&RexxState.array))->res.message = szReceiveString; 
  136.             }
  137.             
  138.             switch(uwStringType)
  139.             {
  140.                 case STRING_USER:       lStringType = 1; break;
  141.                 case STRING_EASYREQREP:   lStringType = 2; break;
  142.                 case STRING_STRINGREQREP: lStringType = 3; break;
  143.                 case STRING_EASYREQ:
  144.                     RemoteEasyReq();    /* We just have to send off our answer--nothing goes to REXX here */
  145.                     break;
  146.                 case STRING_STRINGREQ:
  147.                     RemoteStringReq();
  148.                     break;
  149.                 case STRING_SETWINTITLE:
  150.                     SetWindowTitle(szReceiveString);
  151.                     break;
  152.                 case STRING_REXXCOMMAND:
  153.                     RemoteRexxCommand();
  154.                     break;
  155.                 default:
  156.                     Printf("Invalid stringtype code [%i]\n",uwStringType);
  157.                     break;
  158.             }
  159.             
  160.                     /* Only release an ARexx WaitEvent() if the string was one of the
  161.                        types meant to be sent to ARexx */
  162.             if ((PState.uwRexxWaitMask & REXX_REPLY_MESSAGE)&&
  163.                 ((uwStringType == STRING_USER)||
  164.                  (uwStringType == STRING_EASYREQREP)||
  165.                  (uwStringType == STRING_STRINGREQREP)))
  166.             {    
  167.                 SetStandardRexxReturns();
  168.              }
  169.         }
  170.         else
  171.         {
  172.             memcpy(&szReceiveString[ubStringIndex], &uwNext, 2);
  173.               if (ubStringIndex < 252) ubStringIndex += 2;
  174.         }
  175.         return(TRUE);
  176.     }
  177.  
  178.     if (PState.BPenDown == TRUE) BreakAction(PState.uwMode);
  179.         
  180.     /* We never want to write a Quit from here, because that should only
  181.        be done via HandleIDCMP! */
  182.     if (uwNext == COMMAND_QUIT)
  183.     {
  184.         ReceivedQuitStuff();
  185.         return(FALSE);
  186.     }
  187.  
  188.     if (BEchoToRemote == TRUE) Wprint(uwNext,DEST_PEER);    
  189.     if (CheckStandardEscapes(uwNext) == FALSE)
  190.     {
  191.         switch(PState.uwRemoteMode & ~(MODE_FILLED) & ~(MODE_XOR))
  192.         {            
  193.             case MODE_MODE:
  194.                 /* Check for MODE_FILLED, and MODE_XOR modifiers */
  195.                 if (uwNext & MODE_FILLED)
  196.                 {
  197.                     BFilledFlag = TRUE;
  198.                     uwNext &= ~(MODE_FILLED);
  199.                 }
  200.                 else BFilledFlag = FALSE;
  201.             
  202.                 if (uwNext & MODE_XOR)
  203.                 {
  204.                     BXorFlag = TRUE;
  205.                     uwNext &= ~(MODE_XOR);
  206.                 }
  207.                 else BXorFlag = FALSE;
  208.  
  209.                 switch(uwNext)
  210.                 {
  211.                     case MODE_FIRST:  break;  /* This is only here to force a mode change */
  212.                     case MODE_DOT:      PState.uwRemoteMode = MODE_DOT;    break;
  213.                     case MODE_PEN:      PState.uwRemoteMode = MODE_PEN;    break;
  214.                     case MODE_LINE:   PState.uwRemoteMode = MODE_LINE;   break;
  215.                     case MODE_CIRCLE: PState.uwRemoteMode = MODE_CIRCLE; break;
  216.                     case MODE_SQUARE: PState.uwRemoteMode = MODE_SQUARE; break;
  217.                     case MODE_POLY:      PState.uwRemoteMode = MODE_POLY;   break;
  218.                     case MODE_FLOOD:  PState.uwRemoteMode = MODE_FLOOD;  break;
  219.                     case MODE_DTEXT:  PState.uwRemoteMode = MODE_DTEXT;  break;
  220.                     case MODE_RASTER: PState.uwRemoteMode = MODE_RASTER; break;
  221.                     default:  Printf("Parse error: MODE_MODE [%i]\n",uwNext);
  222.                 }
  223.                 if (BFilledFlag == TRUE) PState.uwRemoteMode |= MODE_FILLED;
  224.                 if (BXorFlag == TRUE)      PState.uwRemoteMode |= MODE_XOR;
  225.                 break;
  226.             
  227.             case MODE_COMMAND:
  228.                 switch(uwNext)
  229.                 {
  230.                     case COMMAND_SIZELOCK:      switch(PState.nSizeState)
  231.                                   {
  232.                                       case SIZEMODE_PASSIVE:
  233.                                           SetWindowTitle("Warning-double SizeLock!");
  234.                                           break;
  235.                                           
  236.                                       case SIZEMODE_NORMAL:
  237.                                           PState.nSizeState = SIZEMODE_PASSIVE;
  238.                                           OutputAction(FROM_IDCMP, COMMAND, COMMAND_SIZEOK, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);
  239.                                           break;
  240.                                           
  241.                                       /* This is a shitty case.  I'm waiting for his okay, and since he sent me a lock
  242.                                          request, that means he'll be waiting for my size-okay.  We need some asymmetry here!
  243.                                          so, if I'm AcceptingTCP, I'll send an Okay and go passive.  If I'm the connect-er,
  244.                                          I'll do nothing but wait for their okay.  */
  245.                                       case SIZEMODE_ACTIVE:
  246.                                           if (BAcceptingTCP == TRUE)
  247.                                           {
  248.                                               PState.nSizeState = SIZEMODE_PASSIVE;
  249.                                               OutputAction(FROM_IDCMP, COMMAND, COMMAND_SIZEOK, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);
  250.                                           }
  251.                                           /* else: do nothing */
  252.                                           break;
  253.                                           
  254.                                       default:
  255.                                           Printf("HandleRemote:  bad nSizeState!\n");
  256.                                           break;
  257.                                   }
  258.                                   PState.uwRemoteMode = nSaveState;
  259.                                   break;
  260.                                   
  261.                     case COMMAND_SIZEUNLOCK:  if (PState.nSizeState == SIZEMODE_PASSIVE) 
  262.                                   {
  263.                                       PState.nSizeState = SIZEMODE_NORMAL;
  264.                                       ReSizeWindow(DrawWindow->Height, DrawWindow->Width, TRUE);
  265.                                   }
  266.     
  267.                                   PState.uwRemoteMode = nSaveState;
  268.                                   break;
  269.                                   
  270.                     case COMMAND_SIZEOK:      if (PState.nSizeState == SIZEMODE_ACTIVE) 
  271.                                   {
  272.                                       /* Draw OUR window now that we know it's ok */
  273.                                       DrawResizedWindow(PState.uwWidth, PState.uwHeight, TRUE);
  274.                                       OutputAction(FROM_IDCMP, COMMAND, COMMAND_SIZE, DrawWindow->Width, DrawWindow->Height, NOP_PAD, DEST_PEER|DEST_FILE);
  275.                                       if (BIFFLoadPending == TRUE) 
  276.                                       {
  277.                                           if (LoadIFF2() == TRUE)        /* Draw our picture now if we were waiting to do that */
  278.                                               SetWindowTitle("IFF Loaded/Transmited.");
  279.                                           else
  280.                                               SetWindowTitle("IFF Load/Transmit failed.");
  281.                                               
  282.                                           ClearPointer(DrawWindow);
  283.                                       }
  284.                                       PState.nSizeState = SIZEMODE_NORMAL;
  285.                                   }
  286.                                   else
  287.                                   SetWindowTitle("Warning--unsolicited SizeOk");
  288.                                   
  289.                                   PState.uwRemoteMode = nSaveState;
  290.                                   break;
  291.  
  292.                     case COMMAND_BEEP:      DisplayBeep(Scr);
  293.                                   PState.uwRemoteMode = nSaveState;
  294.                                   break;
  295.  
  296.                     case COMMAND_CLEARMAP:      for (i=0;i<MAXCOLORS;i++) RemotePenMap[i] = FALSE;
  297.                                   if (BProtectInter == TRUE) 
  298.                                   {
  299.                                       RemotePenMap[0] = 2;    /* Protect GUI pens */
  300.                                       RemotePenMap[1] = 2;
  301.                                       RemotePenMap[2] = 2;
  302.                                       RemotePenMap[3] = 2;
  303.                                   }
  304.                                   PState.uwRemoteMode = nSaveState;
  305.                                   break;
  306.                     
  307.                     case COMMAND_SENDSCREEN:  OutputAction(FROM_IDCMP, COMMAND, COMMAND_LOCK, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER);
  308.                                   TransmitDrawCanvas();
  309.                                   PState.uwRemoteMode = nSaveState;                  
  310.                                   strncpy(szSendString,"Screen synchronization complete.", sizeof(szSendString));
  311.                                                   OutputAction(FROM_IDCMP, COMMAND, COMMAND_SENDSTRING, STRING_SETWINTITLE, NOP_PAD, NOP_PAD, DEST_PEER);
  312.                                                   OutputAction(FROM_IDCMP, COMMAND, COMMAND_UNLOCK, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER);
  313.                                   break;
  314.                                   
  315.                     case COMMAND_LOCK:      EnableDraw(FALSE);
  316.                                   PState.uwRemoteMode = nSaveState;
  317.                                   break;
  318.                     case COMMAND_UNLOCK:  EnableDraw(TRUE);
  319.                                   PState.uwRemoteMode = nSaveState; 
  320.                                   break;
  321.                     case COMMAND_QUIT:    ReceivedQuitStuff(); return(FALSE);
  322.                     case COMMAND_SENDPALETTE:  SetWindowTitle("Transmitting Palette to Remote...");
  323.                                     SendPalette(); 
  324.                                     SetWindowTitle("Ready.");
  325.                                    BPalettesLocked = TRUE;
  326.                                    SetMenuValues();
  327.                                    PState.uwRemoteMode = nSaveState;
  328.                                    break;
  329.                     case COMMAND_CLEAR:   ClearWindow();  
  330.                                   PState.uwRemoteMode = nSaveState; 
  331.                                   break;
  332.                     case COMMAND_HELLO:   BNetConnect = TRUE;
  333.                                   sprintf(sBuf, "Connection to %s established.", targethost);
  334.                                   SetWindowTitle(sBuf);
  335.                                   ClearWindow();
  336.                                   if (PState.uwRexxWaitMask & REXX_REPLY_CONNECT)
  337.                                   {
  338.                                 ((struct rxd_waitevent *) *(&RexxState.array))->res.type    = &lConnectType; 
  339.                                 ((struct rxd_waitevent *) *(&RexxState.array))->res.message = targethost; 
  340.                                 SetStandardRexxReturns();
  341.                                   }
  342.                                   break;
  343.                     case COMMAND_SETCOLOR:PState.uwRemoteMode = MODEC_SETCOLOR; break;
  344.                     case COMMAND_RGB:     PState.uwRemoteMode = MODEC_RGB;   break;
  345.                     case COMMAND_SIZE:    PState.uwRemoteMode = MODEC_SIZE;  break;
  346.                     case COMMAND_SYNCH:   PState.uwRemoteMode = MODEC_SYNCH; break;
  347.                     case COMMAND_SENDSTRING:  PState.uwRemoteMode = MODEC_SENDSTRING;
  348.                                   ubStringIndex = 0;
  349.                                   uwStringType = 0;
  350.                                   break;              
  351.                     case COMMAND_SETRASTER:   PState.uwRemoteMode = MODEC_SETRASTER; break;
  352.                     
  353.                     default:  Printf("Parse error: MODE_COMMAND [%i]\n", uwNext);
  354.                 }
  355.                 break;
  356.                 
  357.             case MODE_DOT:
  358.                 if (FillArgs(uwNext,2) == TRUE) Remote_Dot(wArgs[0], wArgs[1]);
  359.                 break;
  360.     
  361.             case MODE_PEN:
  362.                 if (FillArgs(uwNext,2) == TRUE) 
  363.                 {
  364.                     if ((wArgs[0] == STOP_STRING)||(wArgs[1] == STOP_STRING))    
  365.                         Remote_Pen(-1, -1);    /* end the chain */
  366.                     else
  367.                         Remote_Pen(wArgs[0], wArgs[1]);
  368.                 }
  369.                 break;
  370.                                 
  371.             case MODE_LINE:
  372.                 if (FillArgs(uwNext,4) == TRUE) 
  373.                     Remote_Line(wArgs[0], wArgs[1], wArgs[2], wArgs[3]);
  374.                 break;
  375.  
  376.             case MODE_CIRCLE:
  377.                 if (FillArgs(uwNext,4) == TRUE) Remote_Circle(wArgs[0], wArgs[1], wArgs[2], wArgs[3]);
  378.                 break;
  379.     
  380.             case MODE_SQUARE:
  381.                 if (FillArgs(uwNext,4) == TRUE) Remote_Square(wArgs[0], wArgs[1], wArgs[2], wArgs[3]);
  382.                 break;
  383.                 
  384.             case MODE_FLOOD:
  385.                 if (FillArgs(uwNext,3) == TRUE) Remote_Flood(wArgs[0], wArgs[1], wArgs[2]);
  386.                 break;
  387.  
  388.             case MODE_DTEXT:
  389.                 /* If we ARE echoing this, then it's from a local file, in
  390.                    which case we want text on the BOTTOM line.  If we're NOT
  391.                    echoing, than it's really from the remote guy, so we want
  392.                    text on the TOP line! */
  393.                 DisplayKeyPress(uwNext, BEchoToRemote);
  394.                 break;
  395.         
  396.             case MODE_RASTER:
  397.                 if (FillArgs(uwNext,2) == TRUE)    DrawRasterChunk(wArgs[0],wArgs[1],&PState.RemoteRaster,NULL);
  398.                 break;
  399.                 
  400.             case MODEC_RGB:
  401.                 if (FillArgs(uwNext,2) == TRUE)
  402.                 {
  403.                     /* Decipher 12 righthand bits of word into ints */
  404.                     ubBlue  = (wArgs[0]     ) & 0x000F;
  405.                     ubGreen = (wArgs[0] >> 4) & 0x000F;
  406.                     ubRed   = (wArgs[0] >> 8) & 0x000F;
  407.                     BNotBk  = (wArgs[0] >> 15)& 0x0001;
  408.                     PState.uwRemoteFColor = MatchPalette(ubRed, ubGreen, ubBlue, BNotBk, NULL, NULL);
  409.                     ubBlue  = (wArgs[1]     ) & 0x000F;
  410.                     ubGreen = (wArgs[1] >> 4) & 0x000F;
  411.                     ubRed   = (wArgs[1] >> 8) & 0x000F;
  412.                     BNotBk  = (wArgs[1] >> 15)& 0x0001;
  413.                     PState.uwRemoteBColor = MatchPalette(ubRed, ubGreen, ubBlue, BNotBk, NULL, NULL);
  414.                     PState.uwRemoteMode = nSaveState;
  415.                 }
  416.                 break;
  417.  
  418.             case MODEC_SETCOLOR:
  419.                 if (FillArgs(uwNext,2) == TRUE)
  420.                 {
  421.                     /* Decipher 12 righthand bits of word into ints */
  422.                     ubBlue  = (wArgs[1]     ) & 0x000F;
  423.                     ubGreen = (wArgs[1] >> 4) & 0x000F;
  424.                     ubRed   = (wArgs[1] >> 8) & 0x000F;
  425.                     BNotBk  = (wArgs[1] >> 15)& 0x0001;
  426.                     if (wArgs[0] == (~0))
  427.                     {
  428.                         /* ~0 means "find your own best spot for it" */
  429.                         AdaptNewColor(ubRed, ubGreen, ubBlue, RemotePenMap,FALSE);
  430.                     }
  431.                     else
  432.                     SetRGB4(&Scr->ViewPort, wArgs[0], ubRed, ubGreen, ubBlue);
  433.                     
  434.                     PState.uwRemoteMode = nSaveState;
  435.                 }
  436.                 break;
  437.                 
  438.             case MODEC_SIZE:
  439.                 if (FillArgs(uwNext,2) == TRUE)
  440.                 {
  441.                     ReSizeWindow(wArgs[0], wArgs[1], FALSE);
  442.                     PState.uwRemoteMode = nSaveState;
  443.                 }                
  444.                 break;
  445.  
  446.             case MODEC_SYNCH:
  447.                 if (FillArgs(uwNext, 7) == TRUE)
  448.                 {
  449.                     PState.uwRemoteFColor = wArgs[0];
  450.                     PState.uwRemoteBColor = wArgs[1];
  451.                     if ((wArgs[2] != DrawWindow->Width) || 
  452.                         (wArgs[3] != DrawWindow->Height)) 
  453.                                 ReSizeWindow(Min(wArgs[2], DrawWindow->Width),
  454.                                                  Min(wArgs[3], DrawWindow->Height), FALSE);
  455.                     PState.ubRemoteDepth = wArgs[4];
  456.                     PState.uwRemoteScreenWidth = wArgs[5];
  457.                     PState.uwRemoteScreenHeight = wArgs[6];
  458.  
  459.                     /* Make our maximum window width the minimum of our two widths, and 
  460.                         our maximum window height the minimum of our two heights. */
  461.                     /* use wArgs[0] for the width, wArgs[1] for the height */
  462.                     if (PState.uwRemoteScreenWidth < Scr->Width)
  463.                         wArgs[0] = PState.uwRemoteScreenWidth;
  464.                     else
  465.                         wArgs[0] = 0;
  466.                         
  467.                     if (PState.uwRemoteScreenHeight < Scr->Width)
  468.                         wArgs[1] = PState.uwRemoteScreenHeight;
  469.                     else
  470.                         wArgs[1] = 0;
  471.  
  472.                     /* Set the new limits (0=maintain old limit) */
  473.                     WindowLimits(DrawWindow, 0, 0, wArgs[0], wArgs[1]);
  474.  
  475.                     SetMenuValues();
  476.                 }
  477.                 break;
  478.                 
  479.             case MODEC_SETRASTER:
  480.                 if (FillArgs(uwNext, 5) == TRUE)
  481.                 {
  482.                     PState.RemoteRaster.nRX      = wArgs[0];
  483.                     PState.RemoteRaster.nRY      = wArgs[1];
  484.                     PState.RemoteRaster.nRWidth  = wArgs[2];
  485.                     PState.RemoteRaster.nRHeight = wArgs[3];                    
  486.                     PState.RemoteRaster.nRCurrentOffset = wArgs[4];
  487.                     PState.uwRemoteMode = nSaveState;
  488.                 }
  489.                 break;
  490.  
  491.             case MODE_INVALID:
  492.                 Printf("Parse error: entered the Invalid state! (no beginning MODE_CHANGE/COMMAND?)\n");
  493.                 ResumeAction(PState.uwMode);
  494.                 return(FALSE);            
  495.     
  496.             
  497.             default:
  498.                 Printf("Parse error: unknown state!\n");
  499.                 break;        
  500.         }
  501.     }
  502.  if (PState.BPenDown == TRUE) ResumeAction(PState.uwMode);
  503.  return(TRUE);
  504. }
  505.  
  506.  
  507. /* What to do when our partner has bailed on us */
  508. void ReceivedQuitStuff(void)
  509. {    
  510.     /* Close our end of the socket */
  511.     CloseDrawSocket();
  512.     Delay(30);        /* Necessary to avoid busy-waiting??? */
  513.  
  514.     /* If we encounter a "Quit" and are reading/writing to a local file,
  515.        a generated colorset command might keep us from forgetting to have
  516.        the right color change when we load it in next time? */
  517.     ResumeAction(PState.uwMode);
  518.     return;
  519. }
  520.  
  521.  
  522. /* Transmits all palette values--of our palette is less than or equal to
  523.    the size of their palette, do it on a pen-by-pen basis; if our palette
  524.    is bigger than their palette, do it on a dynamic basis */
  525. void SendPalette(void)
  526. {
  527.     
  528.     UWORD i, uwPaletteSize = (1 << PState.ubDepth);
  529.     
  530.     if (PState.ubDepth > PState.ubRemoteDepth)
  531.     {
  532.         /* dynamic palette transmission */
  533.         OutputAction(FROM_IDCMP, COMMAND, COMMAND_CLEARMAP, NOP_PAD, NOP_PAD, NOP_PAD, DEST_PEER|DEST_FILE);
  534.     
  535.         for (i=0; i<uwPaletteSize; i++)
  536.             OutputAction(FROM_IDCMP, COMMAND, COMMAND_SETCOLOR, (UWORD) (~0), RGBComponents(i), NOP_PAD, DEST_PEER|DEST_FILE);
  537.     }
  538.     else
  539.     {
  540.         /* static palette transmission */
  541.         for (i=0; i<uwPaletteSize; i++)
  542.             OutputAction(FROM_IDCMP, COMMAND, COMMAND_SETCOLOR, i, RGBComponents(i), NOP_PAD, DEST_PEER|DEST_FILE);
  543.     }        
  544.     return;
  545. }    
  546.     
  547.     
  548. void RemoteEasyReq()
  549. {
  550.     char *szTitle, *szMessage, *szGadgets;
  551.     int nResult;
  552.     
  553.     szTitle = szReceiveString;
  554.     szMessage = strchr(szReceiveString, 200);    /* Pos of seperator char */
  555.     if (szMessage == NULL) return;
  556.     *szMessage = '\0';                /* terminate title string */
  557.     szMessage++;
  558.     szGadgets = strchr(szMessage, 200);
  559.     if (szGadgets == NULL) return;
  560.     *szGadgets = '\0';
  561.     szGadgets++;
  562.  
  563.     nResult = MakeReq(szTitle, szMessage, szGadgets);
  564.         
  565.     sprintf(szSendString,"%i",nResult);
  566.     OutputAction(FROM_IDCMP, COMMAND, COMMAND_SENDSTRING, STRING_EASYREQREP, NOP_PAD, NOP_PAD, DEST_PEER);
  567.     return;
  568. }
  569.  
  570.  
  571. /* Asks user whether he wants to run an ARexx command suggested by remote
  572.    ARexx script, and if he agrees, runs it (the user also has the option to
  573.    choose another script to run).  Sends a message to the remote client of
  574.    1 if the user agreed, 2 if he selected another file to run, and 0 on
  575.    failure. */
  576. void RemoteRexxCommand()
  577. {
  578.     char *szFile, *szDirPiece = NULL, *szFilePiece;
  579.     char szRunString[50], szRunBuffer[300], cTemp;
  580.     char szRedirectOrNo[] = ">\0\0";
  581.     int nResult,nTries=0;
  582.     FILE *fpTest = NULL;
  583.         
  584.     szFile = strchr(szReceiveString, 200);
  585.     if (szFile == NULL) return;
  586.     *szFile = '\0';            /* terminate Message substring */
  587.     szFile++;            /* move past to file substring */
  588.  
  589.         fpTest = fopen(szFile,"r");
  590.         if (fpTest == NULL)
  591.         {    
  592.             /* File can't be opened, only allow user to find another */
  593.             sprintf(szRunBuffer,"Remote Rexx Client wants me to run\n%s\nbut I can't find it!",szFile);
  594.             sprintf(szRunString,"Choose Another Script|Cancel");
  595.         nResult = MakeReq(szReceiveString,szRunBuffer,szRunString);
  596.         if (nResult == 1) nResult = 2;    /* Choose own file, below */
  597.         }
  598.         else
  599.         {
  600.         fclose(fpTest);
  601.         sprintf(szRunBuffer,"Remote Rexx Client wants me to run\n%s",szFile);
  602.         sprintf(szRunString,"Run It|Choose Another|Cancel");
  603.         nResult = MakeReq(szReceiveString,szRunBuffer,szRunString);
  604.     }
  605.     
  606.         
  607.     switch(nResult)
  608.     {
  609.         case 1: /* User chose to run as is */
  610.                 break;
  611.                 
  612.         case 2: /* User wants to choose his own file to run */
  613.                 szFilePiece = strrchr(szFile,'/');
  614.                 if (szFilePiece == NULL)
  615.                 {    
  616.                     szFilePiece = strrchr(szFile,':');
  617.                     if (szFilePiece == NULL) szFilePiece = szFile;
  618.                 }
  619.                 if (szFilePiece != szFile) 
  620.                 {
  621.                     cTemp = *szFilePiece; /* Last char in dir */
  622.  
  623.             *szFilePiece = '\0';                    
  624.                     szFilePiece++; /* move past : or / sign */
  625.  
  626.             /* now copy the filename into a temporary buffer */
  627.                     strncpy(szRunBuffer,szFilePiece,sizeof(szRunBuffer));
  628.  
  629.             szFilePiece--;         /* Go back to where : or / was */
  630.             *szFilePiece = cTemp;  /* Replace last char in dir */
  631.             szFilePiece++;
  632.             *szFilePiece = '\0';   /* Now terminate dir */
  633.             
  634.             szFilePiece = szRunBuffer;    /* just filename */                    
  635.             szDirPiece = szFile;        /* What's left is the dir */
  636.                 }
  637.                 
  638.                 
  639.                 if (FileRequest("Choose another ARexx script", szFile, 
  640.                     "Execute", szDirPiece, szFilePiece, FALSE) == FALSE)
  641.                         nResult = 0;
  642.                         
  643.                 break;
  644.  
  645.         default:
  646.                 nResult = 0;    /* Error out */
  647.                 break;
  648.     }
  649.         
  650.     /* Run the script! */
  651.         if (nResult > 0)
  652.         {                
  653.             if (strlen(szRexxOutputFile) == 0) *szRedirectOrNo = '\0';
  654.             sprintf(szRunBuffer,"run >NIL: <NIL: rx %s%s %s %s REMOTE", 
  655.                    szRedirectOrNo, UniqueName(szRexxOutputFile), szFile, rexxHost->portname);
  656.                system(szRunBuffer);
  657.         }
  658.         
  659.     sprintf(szSendString,"%i",nResult);
  660.     OutputAction(FROM_IDCMP, COMMAND, COMMAND_SENDSTRING, STRING_EASYREQREP, NOP_PAD, NOP_PAD, DEST_PEER);        
  661.     return;
  662. }
  663.  
  664.  
  665. void RemoteStringReq()
  666. {
  667.     char szUserStringBuf[250];
  668.     char *szDefaultString, *szTitle, *szMessage, *szToSend;
  669.  
  670.     /* Parse out sub-strings */
  671.     szTitle = szReceiveString;
  672.     szDefaultString = strchr(szReceiveString,MAGIC_BYTE);
  673.     if (szDefaultString == NULL) return;
  674.     *szDefaultString = '\0';        /* Terminate Title string and move on */
  675.     szDefaultString++;
  676.     
  677.     szMessage = strchr(szDefaultString,MAGIC_BYTE);
  678.     if (szMessage == NULL) return;
  679.     *szMessage = '\0';
  680.     szMessage++;
  681.     
  682.     strncpy(szUserStringBuf,szDefaultString,sizeof(szUserStringBuf));
  683.     
  684.     if (GetUserString(szUserStringBuf, szTitle, szMessage, sizeof(szUserStringBuf)) == TRUE)
  685.         szToSend = szUserStringBuf;
  686.         else
  687.         szToSend = "(User aborted)";
  688.  
  689.     strncpy(szSendString,szToSend,sizeof(szSendString));        
  690.     OutputAction(FROM_REXX, COMMAND, COMMAND_SENDSTRING, STRING_STRINGREQREP, NOP_PAD, NOP_PAD, DEST_PEER);
  691.     return;
  692. }
  693.  
  694.         
  695. BOOL Synch(void)
  696. {
  697.     if (BNetConnect == TRUE)
  698.     {
  699.         Wprint(COMMAND, DEST_PEER);
  700.         Wprint(COMMAND_SYNCH, DEST_PEER);
  701.         Wprint(PState.uwFColor, DEST_PEER);
  702.         Wprint(PState.uwBColor, DEST_PEER);
  703.         Wprint((UWORD) DrawWindow->Width, DEST_PEER);
  704.         Wprint((UWORD) DrawWindow->Height, DEST_PEER);
  705.         Wprint((UWORD) PState.ubDepth, DEST_PEER);
  706.         Wprint((UWORD) Scr->Width, DEST_PEER);
  707.         Wprint((UWORD) Scr->Height, DEST_PEER);
  708.         uwPreviousMode = MODE_INVALID;        /* Force mode change on next write */
  709.         return(TRUE);
  710.     }
  711.     return(FALSE);
  712. }
  713.  
  714.  
  715. /* This function will fill out the wArgs array up to the nLastArg'th 
  716.    entry.  When it has filled out the last entry, it will return TRUE
  717.    and reset itself. */
  718. BOOL FillArgs(UWORD uwNext, int nLastArg)
  719. {
  720.     nNextArg++;
  721.     
  722.     wArgs[nNextArg] = uwNext;
  723.     
  724.     if ((nNextArg >= (nLastArg-1))||(nNextArg > MAXARGS))
  725.     {
  726.         ResetArgCount();
  727.         return(TRUE);
  728.     }
  729.     
  730.     return(FALSE);
  731. }
  732.  
  733.  
  734.  
  735.  
  736. void ResetArgCount(void)
  737. {
  738.     nNextArg = -1;
  739.     return;
  740. }
  741.  
  742.  
  743.  
  744.  
  745. /* This function will return us to the correct mode if uwNext is one
  746.    of the special "high" characters (0xFF**).   Returns TRUE if an
  747.    escape was encountered (and thus a mode change effected) */
  748. BOOL CheckStandardEscapes(UWORD uwNext)
  749. {
  750.     switch(uwNext)
  751.     {            
  752.         case COMMAND:
  753.             ResetArgCount();
  754.             nSaveState = PState.uwRemoteMode;
  755.             PState.uwRemoteMode = MODE_COMMAND;
  756.             return(TRUE);
  757.  
  758.         case MODE_CHANGE:
  759.             ResetArgCount();
  760.             PState.uwRemoteMode = MODE_MODE;
  761.             return(TRUE);
  762.                     
  763.         default:
  764.             return(FALSE);
  765.     }
  766. }
  767.     
  768.     
  769.  
  770. /* Prints a UWORD out as two bytes to file or to peer--see remote.h for
  771.    defines for DestCode */    
  772. void Wprint(UWORD uwWord, LONG DestCode)
  773. {
  774.     UWORD wLeftByte, wRightByte;
  775.     UBYTE cLeftByte, cRightByte;
  776.     static char sString[2] = "  ";
  777.     
  778.     wLeftByte  = (uwWord & 0xFF00)>>8;
  779.     wRightByte = uwWord & 0x00FF;
  780.     
  781.     cLeftByte = wLeftByte;
  782.     cRightByte = wRightByte;
  783.     
  784.     if ((DestCode & DEST_FILE)&&(fpOut != NULL)) fprintf(fpOut,"%c%c",cLeftByte,cRightByte);
  785.  
  786.     sString[0] = cLeftByte;
  787.     sString[1] = cRightByte;
  788.     
  789.     if ((DestCode & DEST_PEER)&&(BNetConnect == TRUE)) SendString(sString,2);
  790.     return;
  791. }
  792.  
  793.  
  794.  
  795. /* Reads two bytes in a returns a UWORD */
  796. UWORD Wread(FILE *fpFile, LONG FromCode)
  797. {
  798.     static UWORD uwInstr = 0;
  799.     UWORD uwTemp;
  800.     UBYTE ubNew;
  801.     UBYTE *pu1, *pu2;
  802.     int nBytesReceived;
  803.     BOOL BOutputWord = FALSE;
  804.     static BOOL BFirst = FALSE;
  805.     
  806.     pu1 = &uwTemp;
  807.     pu2 = pu1+1;
  808.     
  809.     if (FromCode & FROM_FILE)
  810.     {
  811.         if (fpFile == NULL) return(NOTSENDABLE);
  812.         if (fread(&uwTemp, sizeof(UWORD), 1, fpFile) != 1) return(NOTSENDABLE);
  813.         return(uwTemp);
  814.     }
  815.     else
  816.     {
  817.         nBytesReceived = Receive((char *) &ubNew, 1);
  818.         
  819.         if (nBytesReceived < 1)    return(SEND_EMPTY);
  820.         
  821.         /* see if there is anything here already--if there is, mark that we
  822.            are going to ship it out during this call */
  823.         if (BFirst == TRUE) 
  824.         {
  825.             BOutputWord = TRUE;
  826.             uwInstr = uwInstr << 8;     /* Shift old data left one byte */
  827.         }
  828.         else
  829.         {
  830.             BFirst = TRUE;
  831.         }
  832.         
  833.         uwInstr |= ubNew;    
  834.     }
  835.  
  836.     if (BOutputWord == TRUE)
  837.     {
  838.          BFirst = FALSE;
  839.          uwTemp = uwInstr;
  840.          uwInstr = 0;
  841.         return(uwTemp);
  842.     }
  843.  
  844.     return(SEND_EMPTY);
  845. }
  846.     
  847.     
  848.     
  849.     
  850.     
  851.  
  852. BOOL OutputAction(UBYTE bFromCode, UWORD uwModeID, UWORD arg1, UWORD arg2, UWORD arg3, UWORD arg4, LONG DestCode)
  853. {
  854.     static UWORD uwPreviousForeGround = -1;
  855.     static UWORD uwPreviousBackGround = -1;
  856.     UWORD *uwCheckForeGround, *uwCheckBackGround;
  857.     ULONG ulStringLength;
  858.         
  859.     /* Parse out whether we're from the Arexx or IDCMP */
  860.     switch(bFromCode)
  861.     {
  862.         case FROM_REXX:
  863.             uwCheckForeGround = &PState.uwRexxFColor;
  864.             uwCheckBackGround = &PState.uwRexxBColor;
  865.             break;
  866.         case FROM_IDCMP:
  867.             uwCheckForeGround = &PState.uwFColor;
  868.             uwCheckBackGround = &PState.uwBColor;
  869.             break;
  870.         case FROM_REMOTE:
  871.             uwCheckForeGround = &PState.uwRemoteFColor;
  872.             uwCheckBackGround = &PState.uwRemoteBColor;
  873.             break;
  874.         default:
  875.             Printf("OutputAction:  Unknown source!\n");
  876.             return(FALSE);
  877.     }
  878.     
  879.     /* Can't send data if we're not connected */
  880.     if (BNetConnect == FALSE) DestCode &= ~(DEST_PEER);
  881.     if (fpOut == FALSE)      DestCode &= ~(DEST_FILE);
  882.     
  883.     /* If nothing to do, don't do it! */
  884.     if (DestCode == FALSE) return(FALSE);
  885.     
  886.     if (uwModeID != COMMAND)
  887.     {    
  888.         /* make sure we're in the correct mode */
  889.         if ((uwModeID != uwPreviousMode) &&
  890.             (uwModeID != MODE_CHANGE))
  891.         {
  892.             uwPreviousMode = uwModeID;
  893.             OutputAction(bFromCode, MODE_CHANGE, uwModeID, NOP_PAD, NOP_PAD, NOP_PAD, DestCode);
  894.         }
  895.         
  896.         /* make sure we have the correct colors */
  897.         if ((arg1 != COMMAND_RGB)    &&
  898.             (uwModeID != MODE_DTEXT) &&
  899.             ((*uwCheckForeGround != uwPreviousForeGround)||
  900.              (*uwCheckBackGround != uwPreviousBackGround)))
  901.         {
  902.             OutputAction(bFromCode, COMMAND, COMMAND_RGB, *uwCheckForeGround, 
  903.                            *uwCheckBackGround, NOP_PAD, DestCode);
  904.             uwPreviousForeGround = *uwCheckForeGround;
  905.             uwPreviousBackGround = *uwCheckBackGround;
  906.         }
  907.     }
  908.             
  909.     /* This is the real, binary output! */
  910.     switch(uwModeID & ~(MODE_XOR) & ~(MODE_FILLED))
  911.     {
  912.         case COMMAND:
  913.             Wprint(COMMAND, DestCode);
  914.             Wprint(arg1, DestCode);
  915.             switch(arg1)
  916.             {
  917.                 case COMMAND_RGB:
  918.                     Wprint(RGBComponents(arg2), DestCode);
  919.                     Wprint(RGBComponents(arg3), DestCode);
  920.                 break;
  921.                 case COMMAND_SIZE:
  922.                     Wprint(arg2, DestCode);
  923.                     Wprint(arg3, DestCode);
  924.                 break;
  925.                 case COMMAND_SETCOLOR:
  926.                     Wprint(arg2, DestCode);
  927.                     Wprint(arg3, DestCode);
  928.                 break;
  929.                 case COMMAND_SENDSTRING:
  930.                     ulStringLength = strlen(szSendString);
  931.                     /* If string length is odd, add an extra byte, 
  932.                        since all instructions should terminate on a 
  933.                        word boundary.  */
  934.                     if ((ulStringLength & 0x0001) == 1L)
  935.                     {
  936.                         strncat(szSendString, PAD_STRING, 1);
  937.                         ulStringLength++;
  938.                     }
  939.                     /* Send string type */
  940.                     Wprint(arg2, DestCode);
  941.                     SendString(szSendString, ulStringLength);
  942.                     Wprint(STOP_STRING, DestCode);
  943.                 break;
  944.                 case COMMAND_SETRASTER:
  945.                     /* Send info from appropriate struct */
  946.                     if (bFromCode == FROM_REXX)
  947.                     {
  948.                         Wprint(PState.RexxRaster.nRX, DestCode);
  949.                         Wprint(PState.RexxRaster.nRY, DestCode);
  950.                         Wprint(PState.RexxRaster.nRWidth, DestCode);
  951.                         Wprint(PState.RexxRaster.nRHeight, DestCode);
  952.                         Wprint(PState.RexxRaster.nRCurrentOffset, DestCode);
  953.                     }
  954.                     else if (bFromCode == FROM_IDCMP)
  955.                     {
  956.                         Wprint(PState.LocalRaster.nRX, DestCode);
  957.                         Wprint(PState.LocalRaster.nRY, DestCode);
  958.                         Wprint(PState.LocalRaster.nRWidth, DestCode);
  959.                         Wprint(PState.LocalRaster.nRHeight, DestCode);
  960.                         Wprint(PState.LocalRaster.nRCurrentOffset, DestCode);
  961.                     }
  962.                     
  963.                 case COMMAND_SENDSCREEN:  break;
  964.                 
  965.                 break;    
  966.             }
  967.             break;    
  968.         case MODE_DOT:
  969.             Wprint(arg1, DestCode);
  970.             Wprint(arg2, DestCode);
  971.             break;
  972.         case MODE_PEN:
  973.             Wprint(arg1, DestCode);
  974.             Wprint(arg2, DestCode);
  975.             break;
  976.         case MODE_LINE:
  977.             Wprint(arg1, DestCode);
  978.             Wprint(arg2, DestCode);
  979.             Wprint(arg3, DestCode);
  980.             Wprint(arg4, DestCode);
  981.             break;
  982.         case MODE_CIRCLE:
  983.             Wprint(arg1, DestCode);
  984.             Wprint(arg2, DestCode);
  985.             Wprint(arg3, DestCode);
  986.             Wprint(arg4, DestCode);
  987.             break;
  988.         case MODE_SQUARE:
  989.             Wprint(arg1, DestCode);
  990.             Wprint(arg2, DestCode);
  991.             Wprint(arg3, DestCode);
  992.             Wprint(arg4, DestCode);
  993.             break;
  994.         case MODE_POLY:
  995.             break;
  996.         case MODE_FLOOD:
  997.             Wprint(arg1, DestCode);
  998.             Wprint(arg2, DestCode);
  999.             Wprint(RGBComponents(arg3), DestCode);
  1000.             break;
  1001.         case MODE_DTEXT:
  1002.             Wprint(arg1, DestCode);
  1003.             break;
  1004.         case MODE_CHANGE:
  1005.             Wprint(uwModeID, DestCode);
  1006.             Wprint(arg1, DestCode);
  1007.             break;
  1008.         case MODE_RASTER:
  1009.             Wprint(arg1, DestCode);
  1010.             Wprint(arg2, DestCode);
  1011.             break;
  1012.         default:
  1013.             Printf("OutputAction:  Error: Unknown mode: [%ux]", (uwModeID & ~(MODE_XOR) & ~(MODE_FILLED)));
  1014.             Printf("OutputAction:  Err...arg1=%i, arg2=%i, arg3=%i, arg4=%i\n",arg1,arg2,arg3,arg4);
  1015.             break;
  1016.     }
  1017.     return TRUE;
  1018.  
  1019.  
  1020. }        
  1021.         
  1022.     
  1023. /* ---------------- REMOTE FUNCTIONS FOR MODE_DOT ------------------ */
  1024. BOOL Remote_Dot(int nX, int nY)
  1025. {
  1026.     BOOL BInWindow = FixPos(&nX, &nY);
  1027.  
  1028.     if (BInWindow == TRUE) 
  1029.     {
  1030.         if (PState.uwRemoteMode & MODE_XOR)
  1031.             SetDrMd(DrawWindow->RPort, COMPLEMENT);
  1032.         else
  1033.             SetAPen(DrawWindow->RPort,PState.uwRemoteFColor); 
  1034.     
  1035.         WritePixel(DrawWindow->RPort,nX,nY);
  1036.         OutputAction(FROM_REMOTE, PState.uwRemoteMode, nX, nY, NOP_PAD, NOP_PAD, DEST_FILE);
  1037.     
  1038.         SetDrMd(DrawWindow->RPort, JAM1);
  1039.     }
  1040.     return(TRUE);
  1041. }
  1042.  
  1043.  
  1044.  
  1045.  
  1046. /* ---------------- REMOTE FUNCTIONS FOR MODE_PEN ------------------ */
  1047. BOOL Remote_Pen(int nX, int nY)
  1048. {
  1049.      BOOL BInWindow;
  1050.     static BOOL BLastIn;
  1051.  
  1052.     if (PState.uwRemoteMode & MODE_XOR)
  1053.         SetDrMd(DrawWindow->RPort, COMPLEMENT);
  1054.     else
  1055.     SetAPen(DrawWindow->RPort,PState.uwRemoteFColor); 
  1056.          
  1057.     /* What to do if this is the end marker for a chain */
  1058.     if ((nX < 0)&&(nY < 0))
  1059.     {
  1060.         if (FixPos(&XPen, &YPen) == TRUE) WritePixel(DrawWindow->RPort, XPen, YPen);
  1061.         OutputAction(FROM_REMOTE, MODE_DOT | (PState.uwRemoteMode & MODE_XOR), XPen, YPen, NOP_PAD, NOP_PAD, DEST_FILE);
  1062.         XPen = -1;
  1063.         YPen = -1;
  1064.         BLastIn = FALSE;
  1065.         SetDrMd(DrawWindow->RPort, JAM1);
  1066.         return(TRUE);
  1067.     }
  1068.  
  1069.     BInWindow = FixPos(&nX, &nY);
  1070.     if ((XPen == -1)&&(YPen == -1))
  1071.     {
  1072.         XPen = nX;
  1073.         YPen = nY;
  1074.         SetDrMd(DrawWindow->RPort, JAM1);
  1075.         return(TRUE);
  1076.     }
  1077.     
  1078.     Move(DrawWindow->RPort, XPen, YPen);    
  1079.     if (BInWindow == TRUE) 
  1080.     {
  1081.         Draw(DrawWindow->RPort, nX, nY);
  1082.         OutputAction(FROM_REMOTE, MODE_LINE | (PState.uwRemoteMode & MODE_XOR), XPen, YPen, nX, nY, DEST_FILE);
  1083.         BLastIn = TRUE;
  1084.     }
  1085.     else
  1086.     {
  1087.         if (BLastIn == TRUE)
  1088.         {
  1089.             Draw(DrawWindow->RPort, nX, nY);
  1090.             OutputAction(FROM_REMOTE, MODE_LINE | (PState.uwRemoteMode & MODE_XOR), XPen, YPen, nX, nY, DEST_FILE);
  1091.         }
  1092.         BLastIn = FALSE;
  1093.     }
  1094.     
  1095.     XPen = nX;
  1096.     YPen = nY;    
  1097.     SetDrMd(DrawWindow->RPort, JAM1);
  1098.     return(BInWindow);
  1099. }
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105. /* ---------------- REMOTE FUNCTIONS FOR MODE_LINE ------------------ */
  1106. /* What to do in MODE_LINE when the user releases the mouse button */
  1107. /* returns true if cursor is in window, else false */
  1108. BOOL Remote_Line(int X1, int Y1, int X2, int Y2)
  1109. {
  1110.     BOOL B1, B2;
  1111.     
  1112.     B1 = FixPos(&X1, &Y1);
  1113.     B2 = FixPos(&X2, &Y2);
  1114.     
  1115.     if (B1||B2)
  1116.     {
  1117.         /* Set Color */
  1118.         if (PState.uwRemoteMode & MODE_XOR)
  1119.             SetDrMd(DrawWindow->RPort, COMPLEMENT);
  1120.         else
  1121.         SetAPen(DrawWindow->RPort,PState.uwRemoteFColor);     
  1122.     
  1123.         /* Draw line */
  1124.         Move(DrawWindow->RPort, X1, Y1);
  1125.         Draw(DrawWindow->RPort, X2, Y2);
  1126.         OutputAction(FROM_REMOTE, PState.uwRemoteMode, X1, Y1, X2, Y2, DEST_FILE);      
  1127.     
  1128.         SetDrMd(DrawWindow->RPort, JAM1);
  1129.         return(TRUE);
  1130.      }
  1131.      return(FALSE);
  1132. }
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139. /* ---------------- REMOTE FUNCTIONS FOR MODE_CIRCLE ------------------ */
  1140. BOOL Remote_Circle(int X, int Y, int RX, int RY)
  1141. {
  1142.     int nTop = Y-RY, nBottom = Y+RY, nLeft = X-RX, nRight = X+RX;
  1143.         
  1144.     /* Only draw this if it still fits in the window! 
  1145.        (This is only a problem if the window has just been resized) */
  1146.     if (FixPos(&X, &Y)&&FixPos(&nLeft,&nTop)&&FixPos(&nRight,&nBottom))
  1147.     {
  1148.         /* Set Color */
  1149.         if (PState.uwRemoteMode & MODE_XOR)
  1150.             SetDrMd(DrawWindow->RPort, COMPLEMENT);
  1151.         else
  1152.         SetAPen(DrawWindow->RPort,PState.uwRemoteFColor);
  1153.     
  1154.         /* Draw final circle */
  1155.         Ellipse(X, Y, RX, RY, ((PState.uwRemoteMode & MODE_FILLED) != FALSE));
  1156.         OutputAction(FROM_REMOTE, PState.uwRemoteMode, X, Y, RX, RY, DEST_FILE);
  1157.         SetDrMd(DrawWindow->RPort, JAM1);
  1158.     }
  1159.      return(TRUE);
  1160. }
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166. /* ---------------- REMOTE FUNCTIONS FOR MODE_SQUARE ------------------ */
  1167. BOOL Remote_Square(int X1, int Y1, int X2, int Y2)
  1168. {
  1169.     BOOL BIn = FALSE;
  1170.     
  1171.     /* Draw final square */
  1172.     BIn =  FixPos(&X1, &Y1);
  1173.     BIn |= FixPos(&X2, &Y2);
  1174.     
  1175.     if (BIn)
  1176.     {
  1177.         /* Set Color */
  1178.         if (PState.uwRemoteMode & MODE_XOR)
  1179.             SetDrMd(DrawWindow->RPort, COMPLEMENT);
  1180.         else
  1181.         SetAPen(DrawWindow->RPort,PState.uwRemoteFColor);     
  1182.  
  1183.         Rectangle(X1, Y1, X2, Y2, ((PState.uwRemoteMode & MODE_FILLED) != FALSE));
  1184.             OutputAction(FROM_REMOTE, PState.uwRemoteMode, X1, Y1, X2, Y2, DEST_FILE);
  1185.         SetDrMd(DrawWindow->RPort, JAM1);
  1186.     }
  1187.      return(TRUE);
  1188. }
  1189.  
  1190.  
  1191.  
  1192.  
  1193. /* ---------------- REMOTE FUNCTIONS FOR MODE_FLOOD ------------------ */
  1194. /* What to do in MODE_FLOOD when the user pushes the left mouse button */
  1195. /* returns true if cursor is in window, else false */
  1196. /* Note that this method of transmitting a flood fill is not very safe */
  1197. /* and that for that reason, this function is only called when         */
  1198. /* Safe Fills (in the Misc. menu) is turned OFF.                       */
  1199. BOOL Remote_Flood(int X1, int Y1, UWORD uwExpectedFilledColor)
  1200.     int nTemp, nExpectedFillPaletteEntry;
  1201.     UBYTE ubBlue, ubGreen, ubRed;
  1202.     BOOL BNotBk;
  1203.     
  1204.     /* Decipher 12 righthand bits of word into R,G,B bytes */
  1205.     ubBlue  = (uwExpectedFilledColor     ) & 0x000F;
  1206.     ubGreen = (uwExpectedFilledColor >> 4) & 0x000F;
  1207.     ubRed   = (uwExpectedFilledColor >> 8) & 0x000F;
  1208.     BNotBk  = (uwExpectedFilledColor >>15) & 0x0001;
  1209.     
  1210.     nExpectedFillPaletteEntry = MatchPalette(ubRed, ubGreen, ubBlue, BNotBk, NULL, NULL);
  1211.                     
  1212.     if (FixPos(&X1, &Y1) == TRUE) 
  1213.     {
  1214.         nTemp = ReadPixel(DrawWindow->RPort,X1,Y1);
  1215.         if ((nExpectedFillPaletteEntry == nTemp) && (PState.uwRemoteFColor != nTemp))
  1216.         {
  1217.             SetAPen(DrawWindow->RPort,PState.uwRemoteFColor);
  1218.             FloodFill(X1, Y1, nExpectedFillPaletteEntry, 0, 0, 0, FALSE);        
  1219.             OutputAction(FROM_REMOTE, MODE_FLOOD, X1, Y1, nExpectedFillPaletteEntry, NOP_PAD, DEST_FILE);
  1220.             return(TRUE);
  1221.         }
  1222.     }
  1223.     return(FALSE);
  1224. }
  1225.